﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using xKnight.Models;
using xKnight.WebCrawling.Core.HTTP;

namespace xKnight.WebCrawling.Core.Authentication
{
    public class Authenticator
    {
        public static Cookie[] Authenticate(AuthenticationSetting authenticationSetting)
        {
            if (authenticationSetting == null)
                return new Cookie[0];
         
            var result = WebCrawler.DownloadPage(authenticationSetting.LoginPageUrl);

            Form[] forms = WebCrawler.ExtractForms(authenticationSetting.LoginPageUrl, result.ResponseText);

            for (int i = 0; i < forms.Length; i++)
            {
                if(forms[i].Action==authenticationSetting.LoginFormAction 
                    && forms[i].Method.ToLower()==authenticationSetting.LoginFormMethod.ToLower())
                {

                    string action = authenticationSetting.LoginFormAction.ToLower();
                    string method= authenticationSetting.LoginFormMethod.ToUpper();
                    string requestText=CreateRequestText(authenticationSetting,forms[i]);
                    FormElement[] elements = forms[i].FormElements.ToArray();

                    HttpWebRequest request = new HttpRequestBuilder()
                    .SetCookieAware(true)
                    .SetKeepAlive(true)
                    .SetHttpMethod(method)
                    .SetContentType(action=="GET" ? null : "application/x-www-form-urlencoded")
                    .SetData(Encoding.UTF8.GetBytes(requestText))
                    .SetUrl(action == "GET" ? (action + requestText) : action)
                    .getHttpWebRequest();

                    return HttpHelper.HandleRequestRedirection(request, result.Cookies).Cookies;
                }
            }

            return new Cookie[0];
        }

        private static string CreateRequestText(AuthenticationSetting authenticationSetting, Form form)
        {
            string postData = "";
            FormElement[] elements = form.FormElements.ToArray();

            for (int i = 0; i < elements.Length; i++)
            {
                FormElement element = elements[i];

                if (!(form.Method == "get" && element.Type == "submit"))
                {
                    string value = null;

                    if (element.Name == authenticationSetting.UsernameField)
                        value = authenticationSetting.UsernameValue;
                    else if (element.Name == authenticationSetting.PasswordField)
                        value = authenticationSetting.PasswordValue;
                    else
                        value=element.Value;

                    postData += string.Format("{0}={1}&", element.Name
                        , HttpUtility.UrlEncode(value));
                }
                    
            }

            if (postData.Length == 0)
                return null;

            postData = postData.Substring(0, postData.Length - 1);

            if (form.Method == "get")
            {
                postData = "?" + postData;
                if (!form.Action.EndsWith("/"))
                    postData = "/" + postData;
            }

            return postData;
        }
    }
}
